<?php
date_default_timezone_set("Asia/Shanghai");
error_reporting(E_ERROR);
require_once 'AutoLoader.php';
require_once 'Define.php';
require_once 'fun/common.php';
require_once 'fun/businessHelper.php';
class Application{
	
	protected $config;
	protected $log;
	protected $child = 0;
	protected $maxChild = 10;
	protected static $instance;
	protected function __construct(){
		new AutoLoader();
		$this->config   = new Config();
		$this->log      = new Log();
		$this->maxChild = $this->config->getKey("maxProcess")->get();
	}
	public static function getInstance(){
		if (!self::$instance) {
			self::$instance = new self();
		}
		return self::$instance;
	}
	
	public function test(){		
		$autoLoad      = new AutoLoader();
		$configClass   = new Config();
		$logClass      = new Log();
		$runData       = $_GET;
		if(isset($runData['m'])) unset($runData['m']);
		if(isset($runData['w'])) unset($runData['w']);
		if(isset($runData['a'])) unset($runData['a']);
		$m = isset($_GET['m'])?$_GET['m']:"";
		$w = isset($_GET['w'])?$_GET['w']:$configClass->getKey("defaultWorker");
		$a = isset($_GET['a'])?$_GET['a']:$configClass->getKey("defaultAction");
		if($m){
			include_once "worker/{$m}/{$w}Worker.php";
		}
		$wClass = $w."Worker";
		if(class_exists($wClass)){
			$worker =	new $wClass(array('module'=>$m,'worker'=>$w,'action'=>$a));			
			$worker->preRun($runData);
			$worker->$a();		
		}else{
			throw new Exception("not find class".$wClass);
		}
	}
	/**
	 * 支持多进程
	 * json_decode
	 * data = array(
	 * 	'runData'=>array(
	 * 		'session'=>
	 * 		'filterCond'=> //过滤条件
	 * 		'filterStr'=> //查询条件
	 *  )
	 *  'module'=>
	 *  'worker'=>
	 *  'action'=>
	 * )
	 * 运行httpsql
	 * @throws Exception
	 */
	public function run(){
		$tcp = getprotobyname("tcp");
		$socket = socket_create(AF_INET, SOCK_STREAM, $tcp);
		if(!$socket){
			echo "创建失败";exit;
		}
		//$socket = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );
		$config = new Config();	
		socket_bind( $socket, $this->config->getKey("socket")->getKey('host')->get(),
		 			$this->config->getKey("socket")->getKey("port")->get() );
		echo $this->config->getKey("socket")->getKey('host')->get();
		echo $this->config->getKey("socket")->getKey("port")->get();
		socket_listen($socket);
		while (true) {
			echo 'go while';			
	    	// 接受一个socketix连接  	    	
		    $connection = socket_accept($socket);
		    //var_dump($connection);		      
		    if(!$connection){  
		        $this->log->errLog("connect fail");  
		    }else{  
		        $this->log->errLog("Socket connected\n");
		        //创建子进程接收数据
		    	$this->forkProcess($connection); 		           
		    }  
		  
		    socket_close($connection);  
		    //关闭 socket  
		    printf("Closed the socket\n");  
		}  	
	}
	
	protected function forkProcess($connection){
		if($this->config->getKey("pcntl")->get()){
			$pid = pcntl_fork();
			if($pid == -1){ //fork 进程失败
				$this->log->errLog("Fork Process Error");
				sleep(1);
			}elseif($pid){ //主进程
				$this->child++;
				if($this->child >= $this->maxChild){
					$dead_id = pcntl_wait($status); //如果子进程数达到最大  阻塞主进程
					//echo 'child:'.$dead_id.' dead';
					$this->child--;
				}
			}else{//子进程
				$cpid = posix_getpid();
				echo 'child process';
				$message = "";
				while ($msg = @socket_read($connection, 1024, PHP_NORMAL_READ)) {
					$this->log->accLog($msg);
					$message .=  $msg;
					echo $msg;
					var_dump(substr($message,-1) == "\n");
					if(substr($message,-1) == "\n"){
						$this->router($connection,$message);
						$message = "";
					}
				}
				socket_close($connection);  
    			//关闭 socket  
    			printf("Closed the socket\n");
    			exit();
				//执行心跳 检查是否端口连接			
				//exit();//子进程要退出
			}
		}else{
			$message = "";
			while ($msg = @socket_read($connection, 10, PHP_NORMAL_READ)) {
				$this->log->accLog($msg);
				$message .=  $msg;
				if(substr($message,-1) == "\n"){
					$this->router($connection,$message);
					$message = "";
				}
				
				//$this->router($connection,$msg);				
			}
		}
	}
	protected function router($connection,$message){		
			$data          = json_decode($message,true);
			$this->log->debLog("child router");
			print_r($data);	
			/* if($this->config->getKey("accessLog")->get()){
				$logClass->accLog($data);
			} */	
			$m        = isset($data['module'])?$data['module']:null;
			$w        = isset($data['worker'])?$data['worker']:$this->config->getKey("defaultWorker");
			$a        = isset($data['action'])?$data['action']:$this->config->getKey("defaultAction");
			$runData  = isset($data['runData'])?$data['runData']:null;			
			try{
				if($m){
					include_once "worker/{$m}/{$w}Worker.php";
				}
				$wClass = $w."Worker";
				if(class_exists($wClass)){
				$worker = new $wClass(array('module'=>$m,'worker'=>$w,'action'=>$a),$connection);
					$worker->preRun($runData);				
					$worker->$a();
				}else{
					throw new Exception("not find class".$wClass);
				}
			}catch(Exception $err){
					//记录日志
					$this->log->errLog(array('errormsg'=>$err->getMessage(),"data"=>$data));
			}					
		
	} 
}